(function() {

new sCanvas("canvas", function() {
	game.init(this);
}, function() {
	console.log("error");
});

var game = (function() {
	
	var sc,
		columns,
		rows,
		$canvas, $controls,
		space,
		speed,
		lastShuffleMove,
		restarting = false;
	
	return {
		
		init: function(sCanvas) {
			var g = this;
			
			sc = sCanvas;
			$canvas = $("#canvas");
			$controls = $("#controls");
			
			$("#restart").click(function() {
				g.restart();
			});
			
			this.restart();
			restarting = true;
		},
		
		restart: function() {
			var i, j,
				g = this;
			
			columns = $("#columns").val();
			rows = $("#rows").val();
			
			space = {
				row: rows - 1,
				column: columns - 1
			};
			
			sc.stopAutorepainting();
			
			//if restarting, do some extra stuff
			if (restarting) {
				$controls.fadeOut();
				$canvas.fadeOut(function() {
					sc.get("tiles").remove(true);
					$("#moves").text(0);
				});
			}
			
			$canvas.queue(function() {
				//resize canvas and view
				sc.width(columns * 40);
				sc.height(rows * 40);

				$canvas.width(sc.width());
				$canvas.height(sc.height());
				
				//create tiles
				for (i = 0; i < rows - 1; i++) {
					for (j = 0; j < columns; j++) {
						g.createTile(i, j);
					}
				}

				for (j = 0; j < columns - 1; j++) {
					g.createTile(i, j);
				}
				
				sc.startAutorepainting(true);
				
				$(this).dequeue();
			});
			
			//fade in
			$controls.fadeIn();
			$canvas.fadeIn();
			
			//shuffle
			$canvas.delay(250).queue(function() {
				g.shuffle(3 * columns * rows);
				$(this).dequeue();
			});
			speed = 250;
		},
		
		createTile: function(row, column) {
			var tile = row * columns + column + 1,
				g = this;
			
			sc.rect({
				x: 20 + 40 * column,
				y: 20 + 40 * row,
				width: 36,
				height: 36,
				fill: null,
				stroke: "#000",
				lineWidth: 2,
				group: "tiles tile" + tile,
				id: "t" + row + "-" + column
			})
			.data("row", row)
			.data("column", column)
			.data("number", tile)
			.click(function() {
				if (g.moveTile(this)) {
					$("#moves").text(+$("#moves").text() + 1);
				}
			});
			
			sc.text(tile, {
				x: 20 + 40 * column,
				y: 20 + 40 * row + 1,
				align: "center",
				baseline: "middle",
				fontSize: 24,
				group: "tiles tile" + tile
			});
		},
		
		moveTile: function(tile) {
			var rowDistance = tile.data("row") - space.row,
				columnDistance = tile.data("column") - space.column,
				switcher;
				
			if (rowDistance === 0 && Math.abs(columnDistance) === 1) {
				sc.get("tile" + tile.data("number")).animate({
					x: (columnDistance === 1 ? "-=" : "+=") + 40
				}, speed);
				
				switcher = space.column;
				space.column = tile.data("column");
				tile.data("column", switcher)
				.attr("id", "t" + tile.data("row") + "-" + tile.data("column"));
				
				return true;
			}

			if (columnDistance === 0 && Math.abs(rowDistance) === 1) {
				sc.get("tile" + tile.data("number")).animate({
					y: (rowDistance === 1 ? "-=" : "+=") + 40
				}, speed);
				
				switcher = space.row;
				space.row = tile.data("row");
				tile.data("row", switcher)
				.attr("id", "t" + tile.data("row") + "-" + tile.data("column"));
				
				return true;
			}
			
			return false;
		},
		
		shuffle: function(moves) {
			var speedSave, random,
				selectors = [ ],
				g = this;
			
			if (space.row > 0 && lastShuffleMove !== "S") {
				selectors.push({
					dir: "N",
					func: function() {
						return sc.get("t" + (space.row - 1) + "-" + space.column);
					}
				});
			}
			if (space.row < rows - 1 && lastShuffleMove !== "N") {
				selectors.push({
					dir: "S",
					func: function() {
						return sc.get("t" + (space.row + 1) + "-" + space.column);
					}
				});
			}
			if (space.column > 0 && lastShuffleMove !== "E") {
				selectors.push({
					dir: "W",
					func: function() {
						return sc.get("t" + space.row + "-" + (space.column - 1));
					}
				});
			}
			if (space.column < columns - 1 && lastShuffleMove !== "W") {
				selectors.push({
					dir: "E",
					func: function() {
						return sc.get("t" + space.row + "-" + (space.column + 1));
					}
				});
			}
			
			speedSave = speed;
			speed = 75;
			
			random = selectors[Math.floor(Math.random() * selectors.length)];
			lastShuffleMove = random.dir;
			this.moveTile(random.func());
			moves--;
			if (moves > 0) {
				setTimeout(function() {
					g.shuffle(moves);
				}, speed);
			}
			
			speed = speedSave;
		}
		
	};
	
}());

}());